package org.opens.text.parseHandle.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import org.opens.util.ReadClassPathFileUtil;
import org.opens.db.constant.DbType;
import org.opens.exception.BusinessException;
import org.opens.freemarker.FreemarkerUtil;
import org.opens.text.config.ParseConfig;
import org.opens.text.config.ParseFromFileConfig;
import org.opens.text.constant.SplitSymbol;
import org.opens.text.entity.ParseTableEntity;
import org.opens.text.parseHandle.ParseHandle;
import org.opens.util.FileUtil;
import org.opens.util.SymbolUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.regex.Pattern;

/**
 * 功能描述
 *
 * @author by zhangyuming
 * @date 2022/9/20
 */
public class FileHandle implements ParseHandle {

    private static final String ftlPath = "text/CreateTable.ftl";

    private static Logger LOGGER = LoggerFactory.getLogger(FileHandle.class);

    private static final Pattern compile = Pattern.compile("create table (.*?) ?\\(([\\s\\S]*?)\\);");

    private static final String mysqlMappingPath = "mapping\\MYSQL.json";

    private static final String oracleMappingPath = "mapping\\ORACLE.json";

    private static final String excelDataConvertMappingKey = "excelDataConvertMapping";

    /**
     * 默认的符号转换规则
     */
    private static Map<String, String> defaultSymbolConvertMap = new HashMap<>();

    /**
     * 默认的列非空转换map
     */
    private static Map<String, Boolean> defaultColumnIsNullConvertMap = new HashMap<>();

    /**
     * 默认的列类型转换
     */
    private static Map<String, String> defaultColumnTypeConvertMap = new HashMap<>();

    static {
        defaultSymbolConvertMap.put("）", ")");
        defaultSymbolConvertMap.put("（", "(");

        defaultColumnIsNullConvertMap.put("是", true);
        defaultColumnIsNullConvertMap.put("否", false);
        defaultColumnIsNullConvertMap.put("Y", true);
        defaultColumnIsNullConvertMap.put("N", false);
    }

    @Override
    public void parse(ParseConfig parseConfig) {
        ParseFromFileConfig parseFromFileConfig = parseConfig.getParseFromFileConfig();
        String fileContent = FileUtil.readFileAsString(parseFromFileConfig.getSourceFilePath());

        if (StrUtil.isEmpty(fileContent)) {
            throw new IllegalArgumentException("转换文件内容为空, 终止转换!");
        }

        // 接收用户传入的转换规则, 且用户传入的优先级高
        if (CollectionUtil.isNotEmpty(parseFromFileConfig.getSymbolConvertMap())) {
            defaultSymbolConvertMap.putAll(parseFromFileConfig.getSymbolConvertMap());
        }

        // 执行符号转换
        String convertFileContent = SymbolUtil.convertChineseSymbolsToEnglishSymbols(fileContent, defaultSymbolConvertMap);

        String[] rows = convertFileContent.split(SplitSymbol.EXCEL_ROW_SPLIT.getValue());

        if (rows.length == 0) {
            throw new IllegalArgumentException("未匹配到正确的行内容, 终止转换!");
        }

        // 使skip从1开始
        Integer skipRowNumber = parseFromFileConfig.getSkipRowNumber() - 1;

        // 计算需要创建的list大小
        List<ParseTableEntity> parseTableEntities = new ArrayList<>(rows.length - parseFromFileConfig.getSkipRowNumber());

        // 如果用户传入了自定义分隔符就使用用户的
        String splitColumnSymbol = SplitSymbol.EXCEL_COLUMN_SPLIT.getValue();
        if (StrUtil.isNotBlank(parseFromFileConfig.getSplitColumnSymbol())) {
            splitColumnSymbol = parseFromFileConfig.getSplitColumnSymbol();
        }

        JSONObject jsonConfig = loadMapping(parseConfig);

        // 加载json配置
        this.parseStepOfLoadJsonData(jsonConfig);

        // varchar类型的默认长度
        final Integer varcharTypeDefaultLength = jsonConfig.getInteger("varcharTypeDefaultLength");

        Map<String, String> columnTypeConvertMap = new HashMap<>();
        JSONObject defaultColumnTypeConvertMap = jsonConfig.getJSONObject("defaultColumnTypeConvertMap");
        Iterator<Map.Entry<String, Object>> iterator1 = defaultColumnTypeConvertMap.entrySet().iterator();
        while (iterator1.hasNext()) {
            Map.Entry<String, Object> next = iterator1.next();
            columnTypeConvertMap.put(next.getKey(), (String) next.getValue());
        }
        // 自定义列转换优先
        Map<String, String> customColumnTypeConvertMap = parseConfig.getParseFromFileConfig().getColumnTypeConvertMap();
        if (customColumnTypeConvertMap != null) {
            columnTypeConvertMap.putAll(customColumnTypeConvertMap);
        }

        // 自定义isNull转换优先
        Map<String, Boolean> customColumnIsNullConvertMap = parseConfig.getParseFromFileConfig().getCustomColumnIsNullConvertMap();
        if (customColumnIsNullConvertMap != null) {
            defaultColumnIsNullConvertMap.putAll(customColumnIsNullConvertMap);
        }

        for (int i = 0; i < rows.length; i++) {
            if (i <= skipRowNumber) {
                continue;
            }

            String rowStr = rows[i];

            // 将所有的特殊字符替换掉
            Iterator<Map.Entry<String, String>> iterator = defaultSymbolConvertMap.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<String, String> next = iterator.next();
                rowStr = rowStr.replaceAll(next.getKey(), next.getValue());
            }

            String[] tempColumns = rowStr.split(splitColumnSymbol);

            int maxColumnIndex = tempColumns.length;

            ParseTableEntity parseTableEntity = new ParseTableEntity();

            if (parseFromFileConfig.getColumnNameIndex() > maxColumnIndex) {
                String errMessage = String.format("指定的[columnNameIndex=%s]不存在, 终止转换!", parseFromFileConfig.getColumnNameIndex());
                throw new IllegalArgumentException(errMessage);
            }

            if (parseFromFileConfig.getColumnTypeIndex() > maxColumnIndex) {
                String errMessage = String.format("指定的[columnTypeIndex=%s]不存在, 终止转换!", parseFromFileConfig.getColumnTypeIndex());
                throw new IllegalArgumentException(errMessage);
            }

            if (parseFromFileConfig.getColumnCommentIndex() > maxColumnIndex) {
                String errMessage = String.format("指定的[columnCommentIndex=%s]不存在, 终止转换!", parseFromFileConfig.getColumnCommentIndex());
                throw new IllegalArgumentException(errMessage);
            }

            if (parseFromFileConfig.getColumnIsNotNullIndex() > maxColumnIndex) {
                String errMessage = String.format("指定的[columnIsNotNullIndex=%s]不存在, 终止转换!", parseFromFileConfig.getColumnIsNotNullIndex());
                throw new IllegalArgumentException(errMessage);
            }

            // 设置列名
            String originalColumnName = tempColumns[parseFromFileConfig.getColumnNameIndex() - 1];
            if (StrUtil.isBlank(originalColumnName)) {
                throw new RuntimeException("列名不能为空!");
            }
            String columnName = StrUtil.toUnderlineCase(originalColumnName);
            // 转为全大写
            parseTableEntity.setColumnName(StrUtil.isBlank(columnName) ? "" : columnName.toUpperCase());

            // 设置注释
            parseTableEntity.setColumnComment(tempColumns[parseFromFileConfig.getColumnCommentIndex() - 1]);

            // 列类型
            String originalColumnType = tempColumns[parseFromFileConfig.getColumnTypeIndex() - 1];
            String convertedColumnType = columnTypeConvertMap.get(originalColumnType);
            if (StrUtil.isBlank(convertedColumnType)) {
                throw new RuntimeException("未配置的列转换类型: " + originalColumnType);
            } else {
                if ("varchar".equalsIgnoreCase(convertedColumnType) || "varchar2".equalsIgnoreCase(convertedColumnType)) {
                    // 如果varchar类型的字段没有设置长度, 则自动添加默认长度
                    if (!convertedColumnType.contains("(")) {
                        convertedColumnType += ("(" + varcharTypeDefaultLength + ")");
                    }
                }
                parseTableEntity.setColumnType(convertedColumnType);
            }

            // 设置列非空
            String originalColumnIsNotNull = tempColumns[parseFromFileConfig.getColumnIsNotNullIndex() - 1];
            if (StrUtil.isBlank(originalColumnIsNotNull)) {
                parseTableEntity.setNotNullFlag(false);
            } else {
                Boolean aBoolean = defaultColumnIsNullConvertMap.getOrDefault(originalColumnIsNotNull, false);
                parseTableEntity.setNotNullFlag(aBoolean);
            }

            parseTableEntities.add(parseTableEntity);
        }


        Map<String, Object> modelMap = new HashMap<>();

        if (parseConfig.getParseFromFileConfig().isAppendPrimaryKey()) {
            ParseTableEntity parseTableEntity = new ParseTableEntity();
            parseTableEntity.setColumnName(parseConfig.getParseFromFileConfig().getAppendPrimaryKeyName());
            parseTableEntity.setColumnType(parseConfig.getParseFromFileConfig().getAppendPrimaryKeyType());
            parseTableEntity.setNotNullFlag(true);
            parseTableEntity.setColumnComment("主键");
        }

        modelMap.put("tableName", parseConfig.getTableName().toUpperCase());
        modelMap.put("tableComment", parseConfig.getTableComment());
        modelMap.put("columnList", parseTableEntities);
        modelMap.put("appendPrimaryKey", parseConfig.getParseFromFileConfig().isAppendPrimaryKey());
        modelMap.put("primaryKeyName", parseConfig.getParseFromFileConfig().getAppendPrimaryKeyName());
        modelMap.put("dbType", parseConfig.getDbType().getTypeName());

        FreemarkerUtil.compileProcess(FileUtil.pathSplicing(parseConfig.getGenPath(), parseConfig.getTableName().toUpperCase() + ".sql"), modelMap, ftlPath);
    }

    public static void main(String[] args) {
        String content = FileUtil.readFileAsString("C:\\Users\\zhangyuming\\Desktop\\公司文件\\gen-code\\a.txt");
        /*Pattern compile = Pattern.compile("create table (.*?) ?\\(([\\s\\S]*?)\\);");
        Matcher matcher = compile.matcher(content);
        while (matcher.find()) {
            System.out.println(matcher.group(1));
            System.out.println(matcher.group(2));
        }*/
        //System.out.println(content);

        String[] splitLines = content.split("\\n");
        System.out.println(splitLines.length);

        for (String splitLine : splitLines) {
            System.out.println(splitLine);
        }
    }

    private JSONObject loadMapping(ParseConfig parseConfig) {
        DbType dbType = parseConfig.getDbType();
        JSONObject excelDataConvertMapping = null;
        if (DbType.MYSQL.equals(dbType)) {
            excelDataConvertMapping = this.getMapping(mysqlMappingPath);
        } else if (DbType.ORACLE.equals(dbType)) {
            excelDataConvertMapping = this.getMapping(oracleMappingPath);
        }
        return excelDataConvertMapping;
    }

    @Override
    public JSONObject getMapping(String path) {
        String mappingJsonStr = ReadClassPathFileUtil.read(path);

        if (StrUtil.isEmpty(mappingJsonStr)) {
            throw new BusinessException("未配置有效json配置! 生成实体失败!");
        }

        return JSONObject.parseObject(mappingJsonStr);
    }

    public void parseStepOfLoadJsonData(JSONObject jsonObject) {
        JSONObject defaultSymbolConvertMapTemp = jsonObject.getJSONObject("defaultSymbolConvertMap");
        Iterator<Map.Entry<String, Object>> iterator = defaultSymbolConvertMapTemp.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, Object> next = iterator.next();
            defaultSymbolConvertMap.put(next.getKey(), (String) next.getValue());
        }
    }

}
